package com.demo.webapp.kcfinder;

import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import com.demo.webapp.kcfinder.action.Action;
import com.demo.webapp.kcfinder.config.ActionConfig;
import com.demo.webapp.kcfinder.config.InterceptorConfig;
import com.demo.webapp.kcfinder.config.PackageConfig;
import com.demo.webapp.kcfinder.config.ResultConfig;
import com.demo.webapp.kcfinder.config.ResultTypeConfig;
import com.demo.webapp.kcfinder.context.ActionContext;
import com.demo.webapp.kcfinder.interceptor.Interceptor;
import com.demo.webapp.kcfinder.result.Result;
import com.demo.webapp.kcfinder.utils.ValueStack;

/**
 * 默认Action执行代理
 * 该对象用来执行Action和处理执行结果的渲染
 * 
 * @author ryuu.kk
 *
 */
public class DefaultActionProxy implements ActionProxy {

	private Map<String, Object> extendtionsMap;
	private PackageConfig packageConfig;
	private ActionConfig config;
	private ActionMapping mapping;
	private ObjectFactory objectFactory;
	private Action action;
	private Result result;
	private List<Interceptor> interceptors;
	
	public DefaultActionProxy(PackageConfig packageConfig, ActionConfig config, ActionMapping mapping, Map<String, Object> extendtionsMap) {
		this.config = config;
		this.mapping = mapping;
		this.packageConfig = packageConfig;
		this.extendtionsMap = extendtionsMap;
		this.objectFactory = new ObjectFactory();
	}
	
	public DefaultActionProxy(PackageConfig packageConfig, ActionConfig config, ActionMapping mapping, Map<String, Object> extendtionsMap, ObjectFactory objectFactory) {
		this.config = config;
		this.mapping = mapping;
		this.packageConfig = packageConfig;
		this.extendtionsMap = extendtionsMap;
		this.objectFactory = objectFactory;
	}
	
	/**
	 * 执行方法
	 */
	@Override
	public String execute() throws Exception {
		
		//Action
		//this.config
		ActionContext context = ActionContext.getContext();
		//extendtionsMap
		action = getAction(this.config);
		context.setAction(action);
		
		Map<String, InterceptorConfig> interceptorConfigMap = this.packageConfig.getInterceptorConfigMap();
		List<String> interceptorList = this.config.getInterceptors();
		String code;
		if (interceptorList.size() > 0) {
			for (String name : interceptorList) {
				//拦截器处理
				InterceptorConfig interceptorConfig = interceptorConfigMap.get(name);
				if (interceptorConfig == null || StringUtils.isEmpty(interceptorConfig.getClassName())) {
					continue;
				}
				Interceptor interceptor = getInterceptor(interceptorConfig);
				code = interceptor.intercept(this, mapping);
			}
		}
		//初始化Action
		action._init();
		
		//执行指定方法
		Method method = action.getClass().getMethod(mapping.getMethod());
		code = (String) method.invoke(action);
		
		//取得执行结果的映射对象
		Map<String, ResultConfig> resultMap = this.config.getResultMap();
		ResultConfig resultConfig = resultMap.get(code);
		if (resultConfig == null) {
			//do unknowResultHandler 
			return null;
		}
		//使用指定Result对象渲染结果
		//String target = resultConfig.getResult();
		result = getResult(resultConfig);
		
		//取得Action的执行结果Map
		Map<String, Object> renderMap = action.resultMap();
		context.setResult(renderMap);
		
		code = result.render(context, resultConfig);
		
		//this.result = null;
		//this.action = null;

		ValueStack stack = context.getValueStack();//.setValue("result", renderMap);
		//将执行结果放入值栈
		if (renderMap != null) {
			Iterator<String> keyInter = renderMap.keySet().iterator();
			while(keyInter.hasNext()) {
				String key = keyInter.next();
				stack.setValue(key, renderMap.get(key));
			}
		}
		
		return code;
	}

	@Override
	public ActionConfig getConfig() {
		return this.config;
	}

	protected Action getAction(ActionConfig actionConfig) throws Exception {
		Object action = null;
		action = this.objectFactory.buildAction(actionConfig, ActionContext.getContext());
		
		//执行Action必须为Action的实现类
		if (!Action.class.isAssignableFrom(action.getClass())) {
			throw new RuntimeException(action.getClass() + " is not implement from " + Action.class);
		}
		//actionClass.getMethod(methodStr);
		return (Action) action;
	}
	
	protected Result getResult(ResultConfig resultConfig) throws Exception {
		
		String type = resultConfig.getType();
		ResultTypeConfig resultTypeConfig = this.packageConfig.getResultType(type);
		
		Object result = this.objectFactory.buildResult(resultTypeConfig);
		if (!Result.class.isAssignableFrom(result.getClass())) {
			throw new RuntimeException(result.getClass() + " is not implement from " + Result.class);
		}
		return (Result) result;
	}
	
	protected Interceptor getInterceptor(InterceptorConfig interceptorConfig) throws Exception {
		
		Object interceptor = this.objectFactory.buildInterceptor(interceptorConfig);
		if (!Interceptor.class.isAssignableFrom(interceptor.getClass())) {
			throw new RuntimeException(interceptor.getClass() + " is not implement from " + Interceptor.class);
		}
		return (Interceptor) interceptor;
	}
	
	public void setObjectFactory(ObjectFactory objectFactory) {
		this.objectFactory = objectFactory;
	}

	@Override
	public Action getAction() throws Exception {
		if (this.action == null){
			this.action = this.getAction(this.config);
		}
		return this.action;
	}

	@Override
	public Result getResult() throws Exception {
		return this.result;
	}

	@Override
	public List<Interceptor> getInterceptors() throws Exception {
		return this.interceptors;
	}
}
